import re
import copy
from decimal import Decimal as Dec

from DataTool import DataTool

class ParseFormula:
    NamesAB = ('表一', '表二', '表二(标)', '表五')
    Math = {'add':'+', 'sub':'-', 'mul':'*', 'div':'/', 'rem':'%', 'Div':'//', 'br':'(', 'abr':')'}
    String = {'and': '&'}
    def __init__(self, mainframe):
        # mainfrom 为实例化的MainFrame类
        self.Pattern = '{{ .*? }}'
        self.MainFrame = mainframe

    def StringParse(self, string):
        # 字符串解析
        if isinstance(string, str):
            index = self.GetFormulaIndexs(string)
            if index is not None:
                All = re.findall(self.Pattern, string)
                AllData = []
                for index, formula in enumerate(All):
                    AllData.append(self.FormulaToList(formula))
                MaxLen = 1
                for i in AllData:  
                    if len(i) > MaxLen:
                        MaxLen = len(i)
                Ret = []
                for i in range(MaxLen):
                    value = string
                    for index,j in enumerate(All):
                        where = value.find(j)
                        if len(AllData[index]) < MaxLen:
                            if len(AllData[index]) != 0:
                                replace = AllData[index][0]
                            else:
                                replace = ''
                        else:
                            replace = AllData[index][i]
                        value = value[0:where] + str(replace) + value[len(All[index])+where:]
                    Ret.append(value)
                
                return Ret

        return [string]

    def FormulaToList(self, string):
        # 独立公式转换为list
        string = string[3:-3]
        string = string.split('__')
        HasMath = False
        HasString = False
        for index, i in enumerate(string):
            if i in self.Math:
                HasMath = True
                string[index] = self.Math[i]
            elif i in self.String:
                HasString = True
                string[index] = self.String[i]
            else:
                string[index] = self.FormulaElementToList(i)

        ret = []
        maxnum = 1

        for i in string:
            if isinstance(i, list):
                if maxnum < len(i):
                    maxnum = len(i)

        if HasMath and not HasString:
            for i in range(maxnum):
                value = ''
                for j in string:
                    if isinstance(j, list):
                        if len(j) == 0:
                            value += '0'
                        elif len(j) < maxnum:
                            value += str(j[0])
                        else:
                            value += str(j[i])
                    else:
                        value += str(j)
                try:
                    value = DataTool().formula2list(value)
                    value = DataTool().listadddec(value)
                    value = DataTool().list2str(value)
                    value = eval(value)
                    value = round(value, 2)
                    ret.append(value)
                except:
                    ret.append('')

        elif not HasMath and HasString:
            while '&' in string:
                string.remove('&')
            for i in range(maxnum):
                value = ''
                for j in string:
                    if isinstance(j, list):
                        if len(j) == 0:
                            value = ''
                            break
                        elif len(j) < maxnum:
                            if str(j[0]) == '':
                                value = ''
                                break
                            value += str(j[0])
                        else:
                            if str(j[i]) == '':
                                value = ''
                                break
                            value += str(j[i])
                    else:
                        if j == '':
                            value = ''
                            break
                        else:
                            value += str(j)
                try:
                    ret.append(value)
                except:
                    ret.append('')

        elif HasMath and HasString:
            ret = ['']

        else:
            ret = string[0]
        
        return ret

    def FormulaElementToList(self, formulaele):
        # 公式元素转换为数据
        Formula = formulaele
        FormulaList = Formula.split('_')
        if FormulaList[0] == 'A':
            # 模式1
            ret = self.PatternA(FormulaList)
        elif FormulaList[0] == "B":
            # 模式2
            ret = self.PatternB(FormulaList)
        elif FormulaList[0] == "C":
            # 模式3
            ret = self.PatternC(FormulaList)
        elif FormulaList[0] == "D":
            # 模式4
            ret = self.PatternD(FormulaList)
        elif FormulaList[0] == "E":
            # 模式5
            ret = self.PatternE(FormulaList)
        elif FormulaList[0] == "F":
            # 模式6
            ret = self.PatternF(FormulaList)
        else:
            ret = Formula

        return ret

    def GetFormulaIndexs(self, string):
        # 找到字符串中第一个公式的索引
        ret = re.search(self.Pattern, string)
        if ret is None:
            return None
        else:
            return ret.span()
    
    def IsSingle(self, string):
        # 判断字符串中是否是单个公式
        ret = re.findall(self.Pattern, string)
        if len(ret) > 1:
            return True
        else:
            return False

    def IsFormula(self, string):
        # 判断字符串内有没有公式
        ret = re.findall(self.Pattern, string)
        if len(ret) == 0:
            return False
        else:
            return True

    def PatternA(self, formulalist):
        try:
            # 初始化数据
            ret = []
            Index = int(formulalist[1])
            TableName = formulalist[2]
            FeeName = formulalist[3]
            if len(formulalist) > 4:
                ColName = formulalist[4]
            else:
                ColName = ''
            
            BookName = self.MainFrame.BookList[Index][1]['分册名称']
            NoteBook = self.MainFrame.FindWindowByName(BookName)
            Data = NoteBook.GetData(TableName)
            Data = copy.deepcopy(Data)
            Grid = NoteBook.getgrid(TableName)
            ColNums = Grid.GetNumberCols()
            # 获取列索引
            if ColName != '':
                for i in range(ColNums):
                    if ColName == Grid.GetColLabelValue(i).replace('\n', ''):
                        ColIndex = i
                        break
            if TableName == '表一':
                for row in Data:
                    if row[1] == FeeName:
                        ret = [row[ColIndex]]
            
            elif TableName == '表二' or TableName == '表二(标)':
                for row in Data:
                    if row[1] == FeeName:
                        ret = [row[ColIndex]]
                    elif row[5] == FeeName:
                        ret = [row[ColIndex + 4]]

            elif TableName == '表五':
                for row in Data:
                    if row[0] == FeeName:
                        ret = [row[ColIndex]]

            elif TableName == '表三甲':
                for row in Data:
                    if row[1] == FeeName:
                        ret = [row[ColIndex]]

            elif TableName == '表四材料':
                if FeeName == '光缆':
                    sumnmu = 0
                    for row in Data:
                        if '光缆' in row[0] and row[2] == '公里':
                            sumnum += float(row[3])
                    ret = [str(sumnmu)]
                elif FeeName == '光缆芯公里':
                    sumcore = Dec('0')
                    for row in Data:
                        if '光缆' in row[0] and row[2] == '公里':
                            FiberCore = self.GetFiberNum(row[1])
                            if DataTool().isnum(FiberCore):
                                sumcore += Dec(str(row[3])) * Dec(str(FiberCore))
                    ret = [str(sumcore)]



        except:
            ret = ['']

        return ret

    def PatternB(self, formulalist):
        try:
            if formulalist[1] == 'P':
                ret = [self.MainFrame.ProData.get(formulalist[2], [''])]
            elif '表' in formulalist[2]:
                BookName = self.MainFrame.BookList[int(formulalist[1])][1]['分册名称']
                NoteBook = self.MainFrame.FindWindowByName(BookName)
                Handler = NoteBook.GetHandler()
                if formulalist[2] == '表一':
                    ret = [Handler.table1rate.get(formulalist[3], '')]
                elif formulalist[2] == '表二(标)':
                    ret = [Handler.table2rate.get(formulalist[3], '')]
                elif formulalist[2] == '表二':
                    ret = [Handler.table2rate.get(formulalist[3], '')]
                else:
                    ret = [getattr(Handler, formulalist[3], '')]
            else:
                index = int(formulalist[1])
                if index >= len(self.MainFrame.BookList):
                    ret = ['']
                else:
                    ret = [self.MainFrame.BookList[index][1].get(formulalist[2], [''])]
        except:
            ret = ['']

        return ret

    def PatternC(self, formulalist):
        try:
            # 初始化数据
            IndexNum = 1
            ret = []
            RowName = ''
            Index = int(formulalist[1])
            TableName = formulalist[2]
            ColName = formulalist[3]
            if len(formulalist) > 4:
                RowName = int(formulalist[4])

            BookName = self.MainFrame.BookList[Index][1]['分册名称']
            NoteBook = self.MainFrame.FindWindowByName(BookName)
            Data = NoteBook.GetData(TableName)
            Data = copy.deepcopy(Data)
            Grid = NoteBook.getgrid(TableName)
            ColNums = Grid.GetNumberCols()
            # 删除Data中末尾为''的数据
            Data.reverse()
            PopIndexes = []
            for index, row in enumerate(Data):
                for value in row:
                    if value != '':
                        break
                if value == '':
                    PopIndexes.append(index)
                else:
                    break
            PopIndexes.reverse()
            for i in PopIndexes:
                Data.pop(i)
            Data.reverse()
            # 获取列索引
            if DataTool().isnum(ColName):
                ColIndex = int(ColName)
            elif ColName == '序号':
                pass
            else:
                for i in range(ColNums):
                    if ColName == Grid.GetColLabelValue(i).replace('\n', ''):
                        ColIndex = i
                        break
            
            if RowName == '':
                ret = []
                for row in Data:
                    if '表三' in TableName:
                        if DataTool().isnum(row[3]) and float(row[3]) == 0:
                            pass
                        elif ColName == '序号':
                            ret.append(str(IndexNum))
                            IndexNum += 1
                        else:
                            ret.append(row[ColIndex])
                    elif '表四' in TableName:
                        if DataTool().isnum(row[7]) and float(row[7]) == 0 or row[7] == '':
                            pass
                        elif ColName == '序号':
                            ret.append(str(IndexNum))
                            IndexNum += 1
                        else:
                            ret.append(row[ColIndex])
                    else:
                        if ColName == '序号':
                            ret.append(str(IndexNum))
                            IndexNum += 1
                        else:
                            ret.append(row[ColIndex])

            else:
                index = 1
                for row in Data:
                    if '表三' in TableName:
                        if DataTool().isnum(row[3]) and float(row[3]) == 0:
                            pass
                        else:
                            if index == RowName:
                                ret = [row[ColIndex]]
                                break
                            elif ColName == '序号':
                                ret = [str(index)]
                            index += 1
                    elif '表四' in TableName:
                        if DataTool().isnum(row[7]) and float(row[7]) == 0 or row[7] == '':
                            pass
                        elif ColName == '序号':
                            ret = [str(index)]
                        else:
                            if index == RowName:
                                ret = [row[ColIndex]]
                                break
                            index += 1
                    else:
                        if ColName == '序号':
                            ret = [str(ColIndex)]
                        else:
                            ret = [Data[RowName][ColIndex]]
                        break
        except:
            ret = ['']
        return ret

    def PatternD(self, formulalist):
        try:
            FullData = []
            ret = []
            IndexNum = 1
            RowName = ''
            TableName = formulalist[1]
            ColName = formulalist[2]
            if len(formulalist) > 3:
                RowName = int(formulalist[3])

            for i in self.MainFrame.BookList:
                BookName = i[1]['分册名称']
                NoteBook = self.MainFrame.FindWindowByName(BookName)
                Data = NoteBook.GetData(TableName)
                Data = copy.deepcopy(Data)
                Grid = NoteBook.getgrid(TableName)
                ColNums = Grid.GetNumberCols()
                # 获取列索引
                if DataTool().isnum(ColName):
                    ColIndex = int(ColName)
                elif ColName == '序号':
                    pass
                else:
                    for i in range(ColNums):
                        if ColName == Grid.GetColLabelValue(i).replace('\n', ''):
                            ColIndex = i
                            break
                for row in Data:
                    if '表三' in TableName:
                        if DataTool().isnum(row[3]) and float(row[3]) == 0 or row[3] == '':
                            pass
                        elif ColName == '序号':
                            ret.append(str(IndexNum))
                            IndexNum += 1
                        else:
                            FullData.append(row[ColIndex])
                    elif '表四' in TableName:
                        if DataTool().isnum(row[3]) and float(row[3]) == 0 or row[3] == '':
                            pass
                        elif ColName == '序号':
                            ret.append(str(IndexNum))
                            IndexNum += 1
                        else:
                            FullData.append(row[ColIndex])
            if RowName == '':
                ret = FullData
            else:
                ret = [FullData[RowName]]
            
        except:
            ret = ['']
        return ret

    def PatternE(self, formulalist):
        try:
            retnum = Dec('0')
            SumNum = Dec('0')
            ret = []
            TableName = formulalist[1]
            FeeName = formulalist[2]
            if len(formulalist) > 3:
                ColName = formulalist[3]
            else:
                ColName = ''

            for i in self.MainFrame.BookList:
                BookName = i[1]['分册名称']
                NoteBook = self.MainFrame.FindWindowByName(BookName)
                Data = NoteBook.GetData(TableName)
                Data = copy.deepcopy(Data)
                Grid = NoteBook.getgrid(TableName)
                ColNums = Grid.GetNumberCols()
                # 获取列索引
                if ColName != '':
                    for i in range(ColNums):
                        if ColName == Grid.GetColLabelValue(i).replace('\n', ''):
                            ColIndex = i
                            break
                if TableName == '表一':
                    for row in Data:
                        if row[1] == FeeName:
                            retnum = row[ColIndex]
                
                elif TableName == '表二' or TableName == '表二(标)':
                    for row in Data:
                        if row[1] == FeeName:
                            retnum = row[ColIndex]
                        elif row[5] == FeeName:
                            retnum = row[ColIndex + 4]

                elif TableName == '表五':
                    for row in Data:
                        if row[0] == FeeName:
                            retnum = row[ColIndex]

                elif TableName == '表三甲':
                    for row in Data:
                        if row[1] == FeeName:
                            retnum = row[ColIndex]


                elif TableName == '表四材料':
                    if FeeName == '光缆':
                        sumnmu = Dec('0')
                        for row in Data:
                            if '光缆' in row[0] and row[2] == '公里':
                                sumnmu += Dec(row[3])
                        retnum = sumnmu
                    elif FeeName == '光缆芯公里':
                        sumcore = 0
                        for row in Data:
                            if '光缆' in row[0] and row[2] == '公里':
                                FiberCore = self.GetFiberNum(row[1])
                                if DataTool().isnum(FiberCore):
                                    sumcore += Dec(row[3]) * Dec(FiberCore)
                        retnum = sumcore

                if DataTool().isnum(retnum):
                    pass
                else:
                    retnum = Dec('0')
                
                SumNum += Dec(retnum)
            ret = [str(SumNum)]
        except:
            ret = ['']

        return ret

    def PatternF(self, formulalist):
        try:
            ret = []
            TableName = formulalist[1]
            ColName = formulalist[2]
            Datas = [[],[],[],[],[],[]]
            
            for index, i in enumerate(self.MainFrame.BookList):
                BookName = i[1]['分册名称']
                NoteBook = self.MainFrame.FindWindowByName(BookName)
                Data = NoteBook.GetData(TableName)
                Data = copy.deepcopy(Data)
                Grid = NoteBook.getgrid(TableName)
                ColNums = Grid.GetNumberCols()
                # 获取列索引
                if ColName == '序号':
                    ColIndex = -1
                else:
                    for i in range(ColNums):
                        if ColName == Grid.GetColLabelValue(i).replace('\n', ''):
                            ColIndex = i
                            break

                if TableName == '表五':
                    for row in Data:
                        if row[0] not in Datas[0]:
                            if index == 0:
                                Datas[0].append(row[0])
                            else:
                                Datas[0].insert(len(Datas[0])-2, row[0])
                        dindex = Datas[0].index(row[0])
                        if index == 0:
                            for i in range(1,6):
                                if i == 1 or i == 5:
                                    Datas[i].append('')
                                else:
                                    Datas[i].append(row[i])
                        else:
                            for i in range(2,5):
                                if DataTool().isnum(row[i]):
                                    if Datas[i][dindex] == '':
                                        Datas[i][dindex] = row[i]
                                    else:
                                        Datas[i][dindex] = str(Dec(Datas[i][dindex]) + Dec(row[i]))
                                else:
                                    pass

            # 删除Datas中不需要的数据
            Datas.pop(-1)
            DatasLen = len(Datas[0])
            for col in Datas:
                if len(col) > DatasLen:
                    for i in range(len(col) - DatasLen):
                        col.pop(-1)

            # 
            if ColIndex != -1:
                ret = Datas[ColIndex]
            else:
                ret = list(range(1, len(Datas[0])+1))

        except:
            ret = ['']

        return ret
    
    def GetFiberNum(self, string):
        ret = ''
        string = string.split('-')[-1]
        for i in string:
            if DataTool().isnum(i):
                ret += i
            else:
                break
        
        return ret

if __name__ == "__main__":
    pass

